package com.zyx.camunda.helpers.listener;

import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.camunda.bpm.engine.impl.bpmn.parser.AbstractBpmnParseListener;
import org.camunda.bpm.engine.impl.core.model.CoreModelElement;
import org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation;
import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.impl.pvm.process.ScopeImpl;
import org.camunda.bpm.engine.impl.util.xml.Element;
import org.camunda.bpm.spring.boot.starter.event.ExecutionEvent;
import org.camunda.bpm.spring.boot.starter.event.PublishDelegateParseListener;
import org.camunda.bpm.spring.boot.starter.event.TaskEvent;
import org.camunda.bpm.spring.boot.starter.property.EventingProperty;
import org.springframework.context.ApplicationEventPublisher;

/**
 * 可以参考 {@link PublishDelegateParseListener} 实现自定义的监听器
 *
 * @author zyx
 * @since 2023/9/28 14:42
 */
@Slf4j
public class CustomBpmnParseListener extends AbstractBpmnParseListener {

    private final TaskListener taskListener;

    /**
     * 这里可以添加到 processDefinition 或者 activity 的 事件中
     */
    private final ExecutionListener executionListener;

    public CustomBpmnParseListener(final ApplicationEventPublisher publisher, final EventingProperty property) {
        if (property.isTask()) {
            this.taskListener = delegateTask -> {
                publisher.publishEvent(delegateTask);
                publisher.publishEvent(new TaskEvent(delegateTask));
            };
        } else {
            this.taskListener = null;
        }
        if (property.isExecution()) {
            this.executionListener = delegateExecution -> {
                publisher.publishEvent(delegateExecution);
                publisher.publishEvent(new ExecutionEvent(delegateExecution));
            };
        } else {
            this.executionListener = null;
        }
    }

    /**
     * 向 processDefinition 中添加监听器
     * <p>可以向 {@link CoreModelElement} 中添加
     * <p>由 {@link AbstractEventAtomicOperation} 中 getListeners(CoreModelElement, CoreExecution)使用
     * <p>使用 scope.getListeners(getEventName()); 调用 而 实现类 getEventName 是固定的
     * <p>因此该方法中 lister 的 eventName 也需要固定，名称可以参考 {@link PublishDelegateParseListener}
     */
    @Override
    public void parseProcess(Element processElement, ProcessDefinitionEntity processDefinition) {
        processDefinition.addListener("end", (ExecutionListener) execution ->
            log.warn("=====>>>>> parseProcess processInstanceId: {} <<<<<=====", execution.getProcessInstanceId())
        );
    }

    @Override
    public void parseEndEvent(Element endEventElement, ScopeImpl scope, ActivityImpl activity) {
        activity.addListener("end", (ExecutionListener) execution ->
            log.warn("=====>>>>> parseEndEvent processInstanceId: {} <<<<<=====", execution.getProcessInstanceId())
        );
    }

}
